package com.hongyi.common.mongoDB.utils;

import cn.hutool.core.util.ObjectUtil;
import com.hongyi.common.framework.constant.HttpStatus;
import com.hongyi.common.framework.exception.ServiceException;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Update;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * mongoDB通用工具类
 *
 * @author DingHao
 * @date 2025/7/7
 **/
public class MongoDbUtils {

    /**
     * 构造修改查询条件（仅包含非空字段）
     *
     * @param t 实体类对象
     * @param c 实体类的 Class 类型
     * @return 返回 Update 对象，可用于 MongoDB 更新操作
     */
    public static<T> Update buildUpdate(T t ,Class<T> c ) {
        Update update = new Update();
        try {
            Field[] fields = c.getDeclaredFields();
            for (Field field : fields) {
                if ("id".equals(field.getName())) {
                    continue; // id 是主键，不需要更新自己
                }
                field.setAccessible(true);
                Object value = field.get(t);
                if (ObjectUtil.isNotEmpty(value)) {
                    update.set(field.getName(), value);
                }
            }
        } catch (IllegalAccessException e) {
            throw new ServiceException("更新数据异常", HttpStatus.ERROR);
        }
        return update;
    }

    /**
     * 根据提供的参数生成查询条件
     *
     * @param map 映射参数
     * @return 返回根据条件构建的查询条件对象
     */
    public static Criteria getCriteria(Map<String, Object> map) {
        return getCriteria(map, null, null, null);
    }

    /**
     * 根据提供的参数生成查询条件
     *
     * @param map 映射参数
     * @param skipFields 需要跳过（不包含）的字段列表
     * @return 返回根据条件构建的查询条件对象
     */
    public static Criteria getCriteria(Map<String, Object> map, List<String> skipFields) {
        return getCriteria(map, skipFields, null, null);
    }

    /**
     * 根据提供的参数生成查询条件
     *
     * @param map 映射参数
     * @param skipFields 需要跳过（不包含）的字段列表
     * @param likeFields 需要进行模糊查询的字段列表
     * @return 返回根据条件构建的查询条件对象
     */
    public static Criteria getCriteria(Map<String, Object> map, List<String> skipFields, List<String> likeFields) {
        return getCriteria(map, skipFields, likeFields, null);
    }

    /**
     * 根据提供的参数生成查询条件
     *
     * @param map 包含查询字段和对应值的映射
     * @param skipFields 需要跳过（不包含）的字段列表
     * @param likeFields 需要进行模糊查询的字段列表
     * @param inFields 需要使用 in 操作符进行查询的字段列表
     * @return 返回根据条件构建的查询条件对象
     */
    private static Criteria getCriteria(Map<String, Object> map, List<String> skipFields, List<String> likeFields, List<String> inFields) {
        Criteria criteria = new Criteria();
        for (String key : map.keySet()) {

            // 过滤掉的字段
            if (skipFields != null && skipFields.contains(key)) {
                continue;
            }

            // 模糊查询的字段
            if (likeFields != null && likeFields.contains(key)) {
                criteria.and(key).regex(".*" + map.get(key) + ".*");
                continue;
            }

            // 使用 in 的查询字段
            if (inFields != null && inFields.contains(key)) {
                criteria.and(key).in(map.get(key));
                continue;
            }

            // TODO: 日期范围查询模板
            if ("startTime".equals(key)) {
                criteria.andOperator(Criteria.where("createTime").gte(formatTime((LocalDateTime) map.get("startTime"))),
                        Criteria.where("createTime").lte(formatTime((LocalDateTime) map.get("endTime"))));
                continue;
            }

            // 其他正常查询字段
            criteria.and(key).is(map.get(key));
        }
        return criteria;
    }

    /**
     * 格式化时间
     */
    private static String formatTime(LocalDateTime time) {
        return time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

}
